package harness;

import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.concurrent.atomic.AtomicStampedReference;

public class TestStampedReferences {

    public static class IntHolder {
        volatile Integer x;
        public IntHolder(int x) {
            this.x = x;
        }
    }
    
    public static void main(String[] args) {
        
        final int ntrials = 5;
        final int iterations = 100000000;
        
        System.out.println("ATOMIC STAMPED REFERENCE");
        for (int i=0;i<ntrials;i++) {
            
            long startTime = System.nanoTime();
            int succ = 0;
            AtomicStampedReference<Integer> ref = new AtomicStampedReference<Integer>(-1, -1);
            for (int j=0;j<iterations;j++) {
                if (ref.compareAndSet(ref.getReference(), j, j-1, j)) ++succ;
                //succ += ref.getReference();
            }
            long elapsed = System.nanoTime() - startTime;
            System.out.println("took " + (elapsed/1000000000.) + "s, " + succ + " successful CASs");
            
        }
        
        System.out.println("ATOMIC REFERENCE");
        for (int i=0;i<ntrials;i++) {
            
            long startTime = System.nanoTime();
            int succ = 0;
            AtomicReference<Integer> ref = new AtomicReference<Integer>(-1);
            for (int j=0;j<iterations;j++) {
                if (ref.compareAndSet(ref.get(), j)) ++succ;
                //succ += ref.get();
            }
            long elapsed = System.nanoTime() - startTime;
            System.out.println("took " + (elapsed/1000000000.) + "s, " + succ + " successful CASs");
            
        }
        
        System.out.println("ATOMIC REFERENCE FIELD UPDATER");
        for (int i=0;i<ntrials;i++) {
            
            long startTime = System.nanoTime();
            int succ = 0;
            AtomicReferenceFieldUpdater<IntHolder, Integer> ref = AtomicReferenceFieldUpdater.newUpdater(IntHolder.class, Integer.class, "x");
            IntHolder x = new IntHolder(-1);
            for (int j=0;j<iterations;j++) {
                if (ref.compareAndSet(x, ref.get(x), j)) ++succ;
                //succ += x.x;
            }
            long elapsed = System.nanoTime() - startTime;
            System.out.println("took " + (elapsed/1000000000.) + "s, " + succ + " successful CASs");
            
        }
        
    }
}
